package com.xyzwps.yaff.core;

import com.xyzwps.yaff.core.commons.Utils;

import java.util.*;

public class SimpleFlowContext implements FlowContext {

    private final HashMap<String, Object> refMap = new HashMap<>();

    private final HashMap<String, Map<String, Object>> privateMap = new HashMap<>();
    private final HashMap<String, Object> publicMap = new HashMap<>();

    private static String validName(String name) {
        if (name == null) {
            throw new YaffException("Name cannot be null");
        }
        if (!Utils.isIdentifier(name)) {
            throw new YaffException("Invalid context variable name: " + name);
        }
        return name;
    }

    @Override
    public void set(String name, Object value) {
        refMap.put(validName(name), value);
    }

    @Override
    public Object get(String name) {
        return refMap.get(name);
    }

    @Override
    public Set<String> getNames() {
        return refMap.keySet();
    }

    @Override
    public Map<String, Object> toMap() {
        return Map.copyOf(refMap);
    }


    private class SimpleNodeContext implements NodeContext {

        private final Map<String, Object> privateContext;

        public SimpleNodeContext(String nodeId) {
            if (!privateMap.containsKey(nodeId)) {
                privateMap.put(nodeId, new LinkedHashMap<>());
            }
            privateContext = privateMap.get(nodeId);
        }

        @Override
        public Object getPrivate(String name) {
            return privateContext.get(name);
        }

        @Override
        public void setPrivate(String name, Object value) {
            privateContext.put(validName(name), value);
        }

        @Override
        public void setPublic(String name, Object value) {
            publicMap.put(validName(name), value);
        }

        @Override
        public Object getPublic(String name) {
            return publicMap.get(name);
        }
    }

    @Override
    public NodeContext getByNodeId(String nodeId) {
        return new SimpleNodeContext(nodeId);
    }
}
